package com.java.basis.io.nio.channel;

import org.junit.Test;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

/**
 * @author wangning
 * @create 2022-01-10 16:25
 */
public class ChannelTest {

	/**
	 * 使用管道写数据
	 * @throws Exception
	 */
	@Test
	public void write() throws Exception {
		//1.得到一个字节输出流通向目标文件
		FileOutputStream os = new FileOutputStream("D:/workspace/idea-workspace/JavaStudyNotes/src/main/java/com/java/basis/io/nio/channel/data01.txt");
		//2.得到字节输出流对应的通道channel
		FileChannel channel = os.getChannel();
		//3.分配缓冲区
		ByteBuffer buffer = ByteBuffer.allocate(1024);
		buffer.put("hello,java程序员".getBytes());
		//4.把缓冲区切换到写出模式
		buffer.flip();
		//5.使用管道写数据
		channel.write(buffer);
		//6.关闭管道
		channel.close();
		System.out.println("写数据到文件中");
	}

	/**
	 * 使用管道读取数据
	 * @throws Exception
	 */
	@Test
	public void read() throws Exception {
		//定义一个原始文件字节输入流用来接收文件
		FileInputStream fs = new FileInputStream("D:/workspace/idea-workspace/JavaStudyNotes/src/main/java/com/java/basis/io/nio/channel/data01.txt");
		//得到文件字节输入流的文件通道
		FileChannel channel = fs.getChannel();
		//定义一个缓冲区
		ByteBuffer buffer = ByteBuffer.allocate(1024);
		//读取数据到缓冲区
		channel.read(buffer);
		//读取缓冲区的数据并输出
		String s = new String(buffer.array(),0,buffer.remaining());

		System.out.println(s);

	}

	/**
	 * 使用管道赋值数据
	 * @throws Exception
	 */
	@Test
	public void copy() throws Exception{
		//源文件
		File file = new File("C:/Users/acer/Desktop/BIO-NIO-AIO/image.png");
		File destFile = new File("C:/Users/acer/Desktop/BIO-NIO-AIO/image_copy.png");
		//得到一个字节输入流、字节输出流
		FileInputStream fis = new FileInputStream(file);
		FileOutputStream fos = new FileOutputStream(destFile);
		//得到文件通道
		FileChannel fisChannel = fis.getChannel();
		FileChannel fosChannel = fos.getChannel();
		//分配缓冲区
		ByteBuffer buffer = ByteBuffer.allocate(1024);
		while (true) {
			//必须先清空缓冲区.在写入数据
			buffer.clear();
			//开始读取一次数据
			int flag = fisChannel.read(buffer);
			if (flag == -1) {
				break;
			}
			//已经读取了数据，把缓冲区的模式切换成可读模式
			buffer.flip();
			//把数据写出去
			fosChannel.write(buffer);
		}
		fis.close();
		fos.close();
		System.out.println("复制完成");
	}

	/**
	 * 分散聚集读取数据
	 * 分散：就是提供多个缓冲区进行读取数据
	 * 聚集：即时把多个缓冲区的数据读出来
	 * @throws Exception
	 */
	@Test
	public void test01() throws Exception {
		//1.字节输入管道
		FileInputStream fis = new FileInputStream("src/main/java/com/java/basis/io/nio/channel/data01.txt");
		FileChannel fisChannel = fis.getChannel();
		//2.字节输出流管道
		FileOutputStream fos = new FileOutputStream("src/main/java/com/java/basis/io/nio/channel/data02.txt");
		FileChannel fosChannel = fos.getChannel();
		//3.定义多个缓冲区
		ByteBuffer buffer1 = ByteBuffer.allocate(4);
		ByteBuffer buffer2 = ByteBuffer.allocate(1024);
		ByteBuffer[] buffers = {buffer1, buffer2};
		//4.从通道中读取数据，分散到各个缓冲区
		fisChannel.read(buffers);
		//5.从每个缓冲区查询是否有数据,分散读取
		for (ByteBuffer buffer : buffers) {
			buffer.flip();//切换到读模式
			System.out.println(new String(buffer.array(), 0, buffer.remaining()));

		}
		//6.聚集写入
		fosChannel.write(buffers);

		fosChannel.close();
		fisChannel.close();
		System.out.println("文件复制完成");


	}

	/**
	 * transferFrom
	 * 把原通道数据复制到目标通道，主要的作用就是转移通道数据
	 */
	@Test
	public void test02() throws Exception {
		//1.字节输入管道
		FileInputStream fis = new FileInputStream("src/main/java/com/java/basis/io/nio/channel/data01.txt");
		FileChannel fisChannel = fis.getChannel();
		//2.字节输出流管道
		FileOutputStream fos = new FileOutputStream("src/main/java/com/java/basis/io/nio/channel/data03.txt");
		FileChannel fosChannel = fos.getChannel();
		//3.复制数据
		fosChannel.transferFrom(fisChannel, fisChannel.position(), fisChannel.size());
		fosChannel.close();
		fisChannel.close();

	}

	/**
	 * transferTo
	 * 把原通道数据复制到目标通道，主要的作用就是转移通道数据
	 */
	@Test
	public void test03() throws Exception {
		//1.字节输入管道
		FileInputStream fis = new FileInputStream("src/main/java/com/java/basis/io/nio/channel/data01.txt");
		FileChannel fisChannel = fis.getChannel();
		//2.字节输出流管道
		FileOutputStream fos = new FileOutputStream("src/main/java/com/java/basis/io/nio/channel/data04.txt");
		FileChannel fosChannel = fos.getChannel();
		fisChannel.transferTo(fisChannel.position(), fisChannel.size(), fosChannel);
		fosChannel.close();
		fisChannel.close();

	}

}
